package edu.nf.relaxenjoy.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import edu.nf.relaxenjoy.common.constant.Constant;
import edu.nf.relaxenjoy.common.constant.auth.AuthConstant;
import edu.nf.relaxenjoy.common.util.JwtUtils;
import edu.nf.relaxenjoy.common.util.RedisUtils;
import edu.nf.relaxenjoy.domain.entity.User;
import edu.nf.relaxenjoy.domain.entity.UserOther;
import edu.nf.relaxenjoy.mapper.UserMapper;
import edu.nf.relaxenjoy.mapper.UserOtherMapper;
import edu.nf.relaxenjoy.service.AuthService;
import edu.nf.relaxenjoy.domain.dto.AuthUserDTO;
import edu.nf.relaxenjoy.domain.dto.UserOtherDTO;
import io.micrometer.common.util.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhu
 * @date 2024-12-11
 */
@Service("authService")
@RequiredArgsConstructor
@Transactional(rollbackFor = RuntimeException.class)
public class AuthServiceImpl implements AuthService {

    private final RedisUtils redisUtils;

    private final UserMapper userMapper;

    private final UserOtherMapper userOtherMapper;

    @Override
    public Map<String, Object> check(AuthUserDTO authUserDTO) {
        return Collections.emptyMap();
    }

    @Override
    public Map<String, Object> login(AuthUserDTO authUserDTO) {
        Map<String, Object> map = new HashMap<>(2);
        String username = authUserDTO.getUsername();
        // 查询当前用户
        User user = userMapper.auth(username);
        String password = SecureUtil.md5(authUserDTO.getPassword());
        if (ObjectUtil.isEmpty(user) || password.equals(user.getPassword())) {
            map.put(AuthConstant.RES, AuthConstant.ERROR_STATUE);
            map.put(AuthConstant.MESSAGE, AuthConstant.ReturnMessage.LOGIN_ERROR.getValue());
            return map;
        }
        String token = JwtUtils.getJwtToken(String.valueOf(user.getUserId()), user.getPassword());
        // 将用户信息保存到redis中
        redisUtils.set(AuthConstant.USER_KEY + user.getUserId(), JSON.toJSONString(user));
        redisUtils.setEx(Constant.FRONT_TOKEN_HEADER + user.getUserId(), token, 2, TimeUnit.DAYS);

        map.put(Constant.FRONT_TOKEN_HEADER, token);
        map.put(AuthConstant.USER_INFO, user);

        return map;
    }

    @Override
    public Map<String, Object> loginByCode(AuthUserDTO authUserDTO) {
        return Collections.emptyMap();
    }

    @Override
    public User getUserInfoByToken(String token) {
        String userId = JwtUtils.getUserId(token);
        User user = userMapper.getUserByUserId(Long.valueOf(userId));
        return user;
    }

    private boolean checkCode(AuthUserDTO authUserDTO, Map<String, Object> map) {

        String code = "";

        if(StringUtils.isNotBlank(redisUtils.get(AuthConstant.CODE+authUserDTO.getPhone()))){
            code = redisUtils.get(AuthConstant.CODE+authUserDTO.getPhone());
        }else if(StringUtils.isNotBlank(redisUtils.get(AuthConstant.CODE+authUserDTO.getEmail()))){
            code = redisUtils.get(AuthConstant.CODE+authUserDTO.getEmail());
        }

        if (StringUtils.isEmpty(code)) {
            map.put(AuthConstant.RES, AuthConstant.ERROR_STATUE.toString());
            map.put(AuthConstant.MESSAGE, AuthConstant.ReturnMessage.CODE_EXPIRE.getValue());
            return true;
        }
        if (!code.equals(authUserDTO.getCode())) {
            map.put(AuthConstant.RES, AuthConstant.ERROR_STATUE.toString());
            map.put(AuthConstant.MESSAGE, AuthConstant.ReturnMessage.CODE_ERROR.getValue());

            return true;
        }
        return false;
    }

    @Override
    public Map<String, Object> regist(AuthUserDTO authUserDTO) {
        Map<String, Object> map = new HashMap<>(2);
        User user = userMapper.authUser(authUserDTO.getPhone(), authUserDTO.getEmail());
        if (user == null) {
            if (checkCode(authUserDTO, map)) {
                return map;
            }

            User rigistUser = new User();
            Long value = Long.valueOf(RandomUtil.randomNumbers(10));
            rigistUser.setUserId(value);
            rigistUser.setId(value);
            rigistUser.setUsername(RandomUtil.randomString(12));
            rigistUser.setPassword(SecureUtil.md5(AuthConstant.DEFAULT_PASSWORD));
            rigistUser.setAvatar(AuthConstant.DEFAULT_AVATAR);
            rigistUser.setCover(AuthConstant.DEFAULT_COVER);
            rigistUser.setPhone(authUserDTO.getPhone());
            rigistUser.setEmail(authUserDTO.getEmail());

            userMapper.rigist(rigistUser);

            // 往第三方登录表中插入数据
            UserOther userOther = new UserOther();
            userOther.setUid(rigistUser.getUserId());
            userOtherMapper.insert(userOther);

            map.put(AuthConstant.RES, AuthConstant.SUCCESS_STATUE.toString());
            map.put(AuthConstant.MESSAGE, AuthConstant.ReturnMessage.SUCCESS_REGIST.getValue());

            String token = JwtUtils.getJwtToken(String.valueOf(rigistUser.getUserId()), rigistUser.getPassword());
            //将用户信息保存在redis中
            redisUtils.set(AuthConstant.USER_KEY + rigistUser.getUserId(), JSON.toJSONString(rigistUser));
            redisUtils.setEx(Constant.FRONT_TOKEN_HEADER+rigistUser.getUserId(),token,2, TimeUnit.DAYS);
            map.put(Constant.FRONT_TOKEN_HEADER, token);
            map.put(AuthConstant.USER_INFO, rigistUser);

            return map;
        } else {
            map.put(AuthConstant.RES, AuthConstant.ERROR_STATUE.toString());
            map.put(AuthConstant.MESSAGE, AuthConstant.ReturnMessage.PHONE_EMAIL_REGIST.getValue());
            return map;
        }
    }

    @Override
    public boolean isRegist(AuthUserDTO authUserDTO) {
        Long count = userMapper.isRigist(authUserDTO.getPhone(), authUserDTO.getEmail());
        return count > 0;
    }

    @Override
    public void loginOut(AuthUserDTO authUserDTO) {
        String key = AuthConstant.USER_KEY + authUserDTO.getUserId();
        String tokenKey = Constant.FRONT_TOKEN_HEADER+authUserDTO.getUserId();
        redisUtils.delete(key);
        redisUtils.delete(tokenKey);
    }

    @Override
    public Boolean updatePassword(AuthUserDTO authUserDTO) {
        return null;
    }

    @Override
    public Map<String, Object> otherLogin(UserOtherDTO userOtherDTO) {
        Map<String, Object> map = new HashMap<>(2);
        //如果是第一次登录
        UserOther userOther = userOtherMapper.select(Long.valueOf(userOtherDTO.getOtherUserId()));
        User user = null;
        if (userOther == null) {

            //注册用户
            user = new User();
            Long value = Long.valueOf(RandomUtil.randomNumbers(10));
            user.setUserId(value);
            user.setId(value);
            user.setUsername(RandomUtil.randomString(12));
            user.setAvatar(userOther.getOtherAvatar());
            user.setCover(AuthConstant.DEFAULT_COVER);

            userMapper.rigist(user);

            //插入到第三方登录表中
            UserOther sourceUserOther = new UserOther();
            sourceUserOther.setId(user.getId());
            sourceUserOther.setUid(user.getUserId());
            sourceUserOther.setOtherUserId(userOtherDTO.getOtherUserId());
            sourceUserOther.setOtherUsername(userOtherDTO.getOtherUsername());
            sourceUserOther.setOtherAvatar(userOtherDTO.getOtherAvatar());

            userOtherMapper.insert(sourceUserOther);
        } else {
            user = userMapper.getUserByUserId(userOther.getUid());
        }

        String token = JwtUtils.getJwtToken(String.valueOf(user.getUserId()), user.getPassword());
        //将用户信息保存在redis中
        redisUtils.set(AuthConstant.USER_KEY + user.getUserId(), JSON.toJSONString(user));
        redisUtils.setEx(Constant.FRONT_TOKEN_HEADER+user.getUserId(),token,2, TimeUnit.DAYS);
        map.put(Constant.FRONT_TOKEN_HEADER, token);
        map.put(AuthConstant.USER_INFO, user);
        return map;
    }

    @Override
    public Map<String, Object> refreshToken(AuthUserDTO authUserDTO) {
        HashMap<String, Object> map = new HashMap<>();
        String token = JwtUtils.getJwtToken(String.valueOf(authUserDTO.getUserId()), authUserDTO.getPassword());
        map.put(Constant.FRONT_TOKEN_HEADER, token);
        map.put(AuthConstant.EXPIRATION, new Date(System.currentTimeMillis() + JwtUtils.EXPIRE));
        return map;
    }
}
